package com.sj.dynamicProxy;

import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.net.URL;
import java.net.URLClassLoader;

public class Test1 {
    public static void main(String[] args) throws Exception {
        String rt = "\r\n";
        String src = "package com.sj.dynamicProxy;" + rt +
                "public class TankTimeProxy implements IMoveable {" + rt +
                "    private IMoveable t;" + rt +

                "    public TankTimeProxy(IMoveable t) {" + rt +
                "        super();" + rt +
                "        this.t = t;" + rt +
                "    }" + rt +

                "    public void move() {" + rt +
                "        long start = System.currentTimeMillis();" + rt +
                "        System.out.println(\"starttime: \" + start);" + rt +
                "        t.move();" + rt +
                "        long end = System.currentTimeMillis();" + rt +
                "        System.out.println(\"time: \" + (end - start));" + rt +
                "    }" + rt +
                "}";

        //先把源代码写到下面
        String fileName = System.getProperty("user.dir") + "/Proxy/src/main/java" + "/com/sj/dynamicProxy/TankTimeProxy.java";
        //user.dir: 当前项目的根路径
        //D:\SpringLearn/Proxy/src/main/java/com/sj/dynamicProxy/TankTimeProxy.java
        File f = new File(fileName);
        FileWriter fw = new FileWriter(f);
        fw.write(src);
        fw.flush();
        fw.close();

        //在程序中编译这段代码
        //JavaCompiler java的编译器
        //ToolProvider.getSystemJavaCompiler() 拿到系统当前默认的java编译器，其实就是javac
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
//        System.out.println(compiler.getClass().getName()); //com.sun.tools.javac.api.JavacTool
        //通过fileMgr管理要编译的文件
        StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
        //拿到编译的内容
        Iterable<? extends JavaFileObject> units = fileMgr.getJavaFileObjects(fileName);
        //编译的任务
        CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);
        t.call(); //编译
        fileMgr.close();

        //生成了这个TankTimeProxy.class之后，将其load到内存，并且生成一个对象
        URL[] urls = new URL[]{new URL("file:/" + System.getProperty("user.dir") + "/Proxy/src/main/java")};
        URLClassLoader ul = new URLClassLoader(urls);
        Class c = ul.loadClass("com.sj.dynamicProxy.TankTimeProxy"); //class com.sj.dynamicProxy.TankTimeProxy
        //c.newInstance(); //调用的是类TankTimeProxy参数为空的构造方法，但是类中没有此构造方法
        //站在java虚拟机的角度，每一个类、每一个类里面的方法都是一个对象；
        Constructor ctr = c.getConstructor(IMoveable.class);
        IMoveable m = (IMoveable) ctr.newInstance(new Tank());
        m.move();
    }
}
